package world3d;

import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.BorderLayout;

import javax.media.j3d.AmbientLight;
import javax.media.j3d.Appearance;
import javax.media.j3d.Background;
import javax.media.j3d.BoundingBox;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.Texture2D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.swing.*;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;
import javax.vecmath.Vector3f;

import com.sun.j3d.utils.geometry.Sphere;
import com.sun.j3d.utils.image.TextureLoader;
import com.sun.j3d.utils.universe.SimpleUniverse;
import com.sun.j3d.utils.universe.ViewingPlatform;

import exp.Node;

public class World3d extends JPanel implements IWorld {
	
	private Canvas3D canvas;
	private SimpleUniverse su;
	private BranchGroup sceneBg;
	private BoundingSphere bounds;
	
	private static final String SKY = "textures/sky_3.jpg";

	public World3d(){
		GraphicsConfiguration config = 
			SimpleUniverse.getPreferredConfiguration();
		canvas = new Canvas3D(config);
		setLayout(new BorderLayout());
		setOpaque(false);
		this.setPreferredSize(new Dimension(512, 512));
		add("Center", canvas);
		canvas.setFocusable(true);
		canvas.requestFocus();
		
		su = new SimpleUniverse(canvas);
		
		init();
		su.addBranchGraph(sceneBg);
	}
	
	private void init(){
		TexturedFloor floor = new TexturedFloor();
		
		sceneBg = new BranchGroup();
		bounds = new BoundingSphere(new Point3d(0, 0, 0), World3dConstants.WORLD_SIZE);
		
		Color3f white = new Color3f(1.0f, 1.0f, 1.0f);
		AmbientLight ambient = new AmbientLight(white);
		ambient.setInfluencingBounds(bounds);
		
		sceneBg.addChild(floor.getFloor());
		sceneBg.addChild(ambient);
		
		lightScene();
		createSky();
		
		sceneBg.compile();
		
		ViewingPlatform vp = su.getViewingPlatform();
		TransformGroup steerTg = vp.getViewPlatformTransform();
		Transform3D t3d = new Transform3D();
		steerTg.getTransform(t3d);
		
		int roadStarts = (World3dConstants.WORLD_SIZE - World3dConstants.ROAD_LENGTH) / 2;
		
		t3d.lookAt(new Point3d(roadStarts - World3dConstants.CELL_SIZE / 2, 1, World3dConstants.WORLD_SIZE / 2), 
				new Point3d(roadStarts - World3dConstants.CELL_SIZE / 2, 1, roadStarts + World3dConstants.ROAD_LENGTH), 
				new Vector3d(0, 1, 0));
		t3d.invert();
		steerTg.setTransform(t3d);
		
		AutomaticBehaviour ab = new AutomaticBehaviour(50, new BoundingBox(floor.getIntersection()[1], floor.getIntersection()[0]));
		
		ab.setSchedulingBounds(bounds);
		vp.setViewPlatformBehavior(ab);
	}
	
	private void lightScene(){
		Color3f white = new Color3f(1.0f, 1.0f, 1.0f);
		
		Vector3f direction = new Vector3f(-1.0f, -1.0f, -1.0f);
		DirectionalLight l1 = new DirectionalLight(white, direction);
		l1.setInfluencingBounds(bounds);
		sceneBg.addChild(l1);
	}
	
	private void createSky(){
		TextureLoader tex = new TextureLoader(SKY, null);
		Texture2D t = (Texture2D)tex.getTexture();
		Appearance app;
		
		Sphere sphere = new Sphere(1.0f,
				Sphere.GENERATE_NORMALS_INWARD |
				Sphere.GENERATE_TEXTURE_COORDS, 15);
		
		app = sphere.getAppearance();
		app.setTexture(t);
		BranchGroup backBg = new BranchGroup();
		backBg.addChild(sphere);
		
		Background bg = new Background();
		bg.setApplicationBounds(bounds);
		bg.setGeometry(backBg);
		
		sceneBg.addChild(bg);
	}
	
	public char getChoice() {
		return '\n';
	}

	public void reset(Node root) {
	}

	public void setNode(Node n) {
	}

	public void transition(Node nextNode) {
	}

	public void move() {
	}
}
